home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
wincap.zip
/
FILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-05
|
9KB
|
329 lines
/*
* file.c
*
* Source file for Device-Independent Bitmap (DIB) API. Provides
* the following functions:
*
* SaveDIB() - Saves the specified dib in a file
* LoadDIB() - Loads a DIB from a file
* DestroyDIB() - Deletes DIB when finished using it
*
* Development Team: Mark Bader
* Patrick Schreiber
* Garrett McAuliffe
* Eric Flo
* Tony Claflin
*
* Written by Microsoft Product Support Services, Developer Support.
* Copyright (c) 1991 Microsoft Corporation. All rights reserved.
*/
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <direct.h>
#include <stdlib.h>
#include "errors.h"
#include "dibutil.h"
#include "dibapi.h"
/*
* Dib Header Marker - used in writing DIBs to files
*/
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
/*********************************************************************
*
* Local Function Prototypes
*
*********************************************************************/
HANDLE ReadDIBFile(int);
BOOL MyRead(int, LPSTR, DWORD);
BOOL SaveDIBFile(void);
BOOL WriteDIB(LPSTR, HANDLE);
DWORD PASCAL MyWrite(int, VOID FAR *, DWORD);
/*************************************************************************
*
* LoadDIB()
*
* Loads the specified DIB from a file, allocates memory for it,
* and reads the disk file into the memory.
*
* Parameters:
*
* LPSTR lpFileName - specifies the file to load a DIB from
*
* Returns: A handle to a DIB, or NULL if unsuccessful.
*
*************************************************************************/
HDIB LoadDIB(LPSTR lpFileName)
{
HDIB hDIB;
int hFile;
OFSTRUCT ofs;
/*
* Set the cursor to a hourglass, in case the loading operation
* takes more than a sec, the user will know what's going on.
*/
SetCursor(LoadCursor(NULL, IDC_WAIT));
if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)
{
hDIB = ReadDIBFile(hFile);
_lclose(hFile);
SetCursor(LoadCursor(NULL, IDC_ARROW));
return hDIB;
}
else
{
DIBError(ERR_FILENOTFOUND);
SetCursor(LoadCursor(NULL, IDC_ARROW));
return NULL;
}
}
/*************************************************************************
*
* SaveDIB()
*
* Saves the specified DIB into the specified file name on disk. No
* error checking is done, so if the file already exists, it will be
* written over.
*
* Parameters:
*
* HDIB hDib - Handle to the dib to save
*
* LPSTR lpFileName - pointer to full pathname to save DIB under
*
* Return value: 0 if successful, or one of:
* ERR_INVALIDHANDLE
* ERR_OPEN
* ERR_LOCK
*
*************************************************************************/
WORD SaveDIB(HDIB hDib, LPSTR lpFileName)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
int fh; // file handle for opened file
OFSTRUCT of; // OpenFile structure
if (!hDib)
return ERR_INVALIDHANDLE;
fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);
if (fh == -1)
return ERR_OPEN;
/*
* Get a pointer to the DIB memory, the first of which contains
* a BITMAPINFO structure
*/
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpBI)
return ERR_LOCK;
/*
* Fill in the fields of the file header
*/
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
/* Size is size of packed dib in memory plus size of file header */
bmfHdr.bfSize = GlobalSize(hDib) + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/*
* Now, calculate the offset the actual bitmap bits will be in
* the file -- It's the Bitmap file header plus the DIB header,
* plus the size of the color table.
*/
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
PaletteSize((LPSTR)lpBI);
/* Write the file header */
_lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
/*
* Write the DIB header and the bits -- use local version of
* MyWrite, so we can write more than 32767 bytes of data
*/
MyWrite(fh, (LPSTR)lpBI, GlobalSize(hDib));
GlobalUnlock(hDib);
_lclose(fh);
return 0; // Success code
}
/*************************************************************************
*
* DestroyDIB ()
*
* Purpose: Frees memory associated with a DIB
*
* Returns: Nothing
*
*************************************************************************/
WORD DestroyDIB(HDIB hDib)
{
GlobalFree(hDib);
return 0;
}
//************************************************************************
//
// Auxiliary Functions which the above procedures use
//
//************************************************************************
/*************************************************************************
Function: ReadDIBFile (int)
Purpose: Reads in the specified DIB file into a global chunk of
memory.
Returns: A handle to a dib (hDIB) if successful.
NULL if an error occurs.
Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
from the end of the BITMAPFILEHEADER structure on is
returned in the global memory handle.
*************************************************************************/
HANDLE ReadDIBFile(int hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HANDLE hDIB;
LPSTR pDIB;
/*
* get length of DIB in bytes for use when reading
*/
dwBitsSize = filelength(hFile);
/*
* Go read the DIB file header and check if it's valid.
*/
if ((_lread(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(
bmfHeader)) || (bmfHeader.bfType != DIB_HEADER_MARKER))
{
return NULL;
}
/*
* Allocate memory for DIB
*/
hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = GlobalLock(hDIB);
/*
* Go read the bits.
*/
if (!MyRead(hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
{
GlobalUnlock(hDIB);
GlobalFree(hDIB);
return NULL;
}
GlobalUnlock(hDIB);
return hDIB;
}
/*************************************************************************
Function: MyRead (int, LPSTR, DWORD)
Purpose: Routine to read files greater than 64K in size.
Returns: TRUE if successful.
FALSE if an error occurs.
Comments:
*************************************************************************/
BOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)
{
char huge *lpInBuf = (char huge *)lpBuffer;
int nBytes;
/*
* Read in the data in 32767 byte chunks (or a smaller amount if it's
* the last chunk of data read)
*/
while (dwSize)
{
nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));
if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)
return FALSE;
dwSize -= nBytes;
lpInBuf += nBytes;
}
return TRUE;
}
/****************************************************************************
FUNCTION : MyWrite(int fh, VOID FAR *pv, DWORD ul)
PURPOSE : Writes data in steps of 32k till all the data is written.
Normal _lwrite uses a WORD as 3rd parameter, so it is
limited to 32767 bytes, but this procedure is not.
RETURNS : 0 - If write did not proceed correctly.
number of bytes written otherwise.
****************************************************************************/
DWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)
{
DWORD dwBytesTmp = dwBytes; // Save # of bytes for return value
BYTE huge *hpBuffer = lpBuffer; // make a huge pointer to the data
/*
* Write out the data in 32767 byte chunks.
*/
while (dwBytes > 32767)
{
if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)
return 0;
dwBytes -= 32767;
hpBuffer += 32767;
}
/* Write out the last chunk (which is < 32767 bytes) */
if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)
return 0;
return dwBytesTmp;
}